import path from 'path';

import { expect } from '@jest/globals';
import * as compressing from 'compressing';
import fse from 'fs-extra';
import JSON5 from 'json5';

import { initExecuteCommand, runHvigorAsync } from '../../common/common';
import { addOhPackageDps } from '../../plugins/common-fun';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType,
} from '../../plugins/project-builder/models/constants';
import { TestCaseBuilder } from '../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../plugins/task-builder/test-case';
import { TestTaskOptionBuilder } from '../../plugins/task-builder/test-task-option';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: APIVersion.API11,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility,
  },
  modulesOption: {
    [ModuleTemplateType.SharedLibrary]: 1,
    [ModuleTemplateType.StaticLibrary]: 1,
  },
};

const testFun: TestCaseFun = async (project, taskConfig, record) => {
  const projectRootPath = project.projectRootPath();
  // sync
  const syncCommands = initExecuteCommand({
    mode: 'project',
    product: 'default',
    tasks: '--sync',
  });
  const syncResult = await runHvigorAsync(projectRootPath, syncCommands);
  record.addStep('sync', syncResult);
  expect(syncResult.stdout).toContain('Finished ::init...');

  // 验证hsp编译
  const hspModuleRootPath = project.getModule('shareLibrary').moduleRootPath();
  // 读取hsp build-profile.json5
  const hspBuildProfile = await fse.readFile(path.resolve(hspModuleRootPath, 'build-profile.json5'));
  const hspBuildProfileJson = JSON5.parse(hspBuildProfile.toString());
  // 将ruleOptions.enable置为true
  hspBuildProfileJson.buildOptionSet[0].arkOptions.obfuscation.ruleOptions.enable = true;
  if (hspBuildProfileJson.buildOptionSet[0].arkOptions.obfuscation.consumerFiles === undefined) {
    hspBuildProfileJson.buildOptionSet[0].arkOptions.obfuscation.consumerFiles = ['./consumer-rules.txt'];
  }
  if (!hspBuildProfileJson.buildOptionSet[0].arkOptions.obfuscation.consumerFiles.includes('./consumer-rules.txt')) {
    hspBuildProfileJson.buildOptionSet[0].arkOptions.obfuscation.consumerFiles.push('./consumer-rules.txt');
  }
  await fse.writeFile(path.resolve(hspModuleRootPath, 'build-profile.json5'), JSON.stringify(hspBuildProfileJson));
  // 判断是否存在consumer-rules.txt文件，不存在则创建，并写入混淆规则
  const hspConsumerRulesPath = path.resolve(hspModuleRootPath, 'consumer-rules.txt');
  fse.ensureFileSync(hspConsumerRulesPath); // -keep-property-name age
  const hspObfuscationRules = '-keep-global-name\nPerson';
  fse.appendFileSync(hspConsumerRulesPath, hspObfuscationRules);
  // 编译构建hsp包
  const buildHspCommand =
    '--mode module -p product=default -p module=shareLibrary@default -p buildMode=release assembleHsp --info ' +
    '--analyze=advanced --parallel --incremental --no-daemon';
  const hspBuildResult = await runHvigorAsync(projectRootPath, buildHspCommand.split(' '));
  record.addStep('buildHsp', hspBuildResult);
  expect(hspBuildResult.stdout).toContain('BUILD SUCCESSFUL');
  // 解压缩hsp的har包，查看是否存在obfuscation.txt文件，并且文件中存在consumer-rules.txt的规则
  const hspHarPackagePath = path.resolve(hspModuleRootPath, 'build/default/outputs/default/shareLibrary.har');
  fse.copyFileSync(hspHarPackagePath, path.resolve(hspModuleRootPath, 'build/default/outputs/default/shareLibrary.tgz'));
  await compressing.tgz.uncompress(
    path.resolve(hspModuleRootPath, 'build/default/outputs/default/shareLibrary.tgz'),
    path.resolve(hspModuleRootPath, 'build/default/outputs/default/shareLibrary'),
  );
  const hspObfuscationPath = path.resolve(hspModuleRootPath, 'build/default/outputs/default/shareLibrary/package/obfuscation.txt');
  expect(fse.existsSync(hspObfuscationPath)).toEqual(true);
  const hspObfuscationTxt = await fse.readFile(hspObfuscationPath);
  expect(replaceLines(hspObfuscationTxt.toString()) === replaceLines(hspObfuscationRules)).toEqual(true);

  // har依赖hsp，编译构建har，验证是否将hsp的consumer-rules.txt打到包里
  const harModuleRootPath = project.getModule('staticLibrary').moduleRootPath();
  await addOhPackageDps(harModuleRootPath, {
    shareLibrary: 'file:../shareLibrary',
  });
  // 读取har的build-profile.json5
  const harBuildProfile = await fse.readFile(path.resolve(harModuleRootPath, 'build-profile.json5'));
  const harBuildProfileJson = JSON5.parse(harBuildProfile.toString());
  harBuildProfileJson.buildOptionSet[0].arkOptions.obfuscation.ruleOptions.enable = true;
  await fse.writeFile(path.resolve(harModuleRootPath, 'build-profile.json5'), JSON.stringify(harBuildProfileJson));
  // 编译构建har
  const buildHarCommand =
    '--mode module -p product=default -p module=staticLibrary@default -p buildMode=release ' +
    'assembleHar --info --analyze=advanced --parallel --incremental --no-daemon';
  const harBuildResult = await runHvigorAsync(projectRootPath, buildHarCommand.split(' '));
  record.addStep('harBuild', harBuildResult);
  expect(harBuildResult.stdout).toContain('BUILD SUCCESSFUL');
  // 检查har编译后的产物中是否有hsp的混淆规则
  const harPackagePath = path.resolve(harModuleRootPath, 'build/default/outputs/default/staticLibrary.har');
  fse.copyFileSync(harPackagePath, path.resolve(harModuleRootPath, 'build/default/outputs/default/staticLibrary.tgz'));
  await compressing.tgz.uncompress(
    path.resolve(harModuleRootPath, 'build/default/outputs/default/staticLibrary.tgz'),
    path.resolve(harModuleRootPath, 'build/default/outputs/default/staticLibrary'),
  );
  const harObfuscationPath = path.resolve(harModuleRootPath, 'build/default/outputs/default/staticLibrary/package/obfuscation.txt');
  expect(fse.existsSync(harObfuscationPath)).toEqual(true);
  const harObfuscationTxt = await fse.readFile(harObfuscationPath);
  expect(replaceLines(harObfuscationTxt.toString()) === replaceLines(hspObfuscationRules)).toEqual(true);
};

/**
 * 正则表达式，去除回车换行
 * @param str
 */
function replaceLines(str: string) {
  return str.replace(/[\r\n]+/g, '');
}

// SDK未配套交付, E2E暂时屏蔽
TestCaseBuilder.builder()
  .caseName('AR20241031411307')
  .description(
    '1 创建stage工程；\n' +
      '2 创建har依赖和hsp依赖；\n' +
      '3 sync；\n' +
      '4 编译构建hsp模块，验证生成的.har包里有没有混淆文件；\n' +
      '5 har模块依赖hsp模块，并编译构建har模块，验证是否将hsp的混淆规则打进去；\n'
  )
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.AR).build())
  .testFun(testFun)
  .load();
